package proyectoia;

import IA.DistFS.Servers;
import aima.search.framework.GoalTest;
import aima.search.framework.HeuristicFunction;
import aima.search.framework.Search;
import aima.search.framework.SuccessorFunction;
import aima.search.informed.HillClimbingSearch;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;

public class StagedExperiment8 extends StagedExperiment {

    public StagedExperiment8(int seed, int nIterations) {
        super(seed, nIterations);
        numStages = 1;
    }

    @Override
    protected int getNumUsers() {
        return 200;
    }

    @Override
    protected int getNumRequests() {
        return 5;
    }

    @Override
    protected int getNumServers() {
        return 50;
    }

    @Override
    protected int getNumReplications() {
        return 5;
    }

    @Override
    protected DistFileSystemState getInitialSolution(DistFileSystemState state) {
        state.generateEmptySolution();
        return state;
    }

    @Override
    protected Search getSearch() {
        return new HillClimbingSearch();
    }

    @Override
    protected SuccessorFunction getSuccessor() {
        return new DistFileSystemSuccessorFunction3();
    }

    @Override
    protected GoalTest getGoalTest() {
        return new DistFileSystemGoalTest();
    }

    @Override
    protected HeuristicFunction getHeuristic() {
        System.out.println(150);
        return new DistFileSystemHeuristicFunction3((float)0.5, (float)150);
//         return new DistFileSystemHeuristicFunction3((float)0.5, (float)1);
    }
    
    public void printServerTime(String filename) throws Exception {
        FileWriter outFile = new FileWriter("data/" + filename + "-slowest-server-time.data");
        PrintWriter o = new PrintWriter(outFile);
        o.println("# Slowest server time");
        System.out.println("Resultats per " + numIterations + " iteracions.");
        for (int s = 0; s < numStages; s++) {
            SummaryStatistics is = new SummaryStatistics();
            SummaryStatistics id = new SummaryStatistics();
            for (int i = 0; i < numIterations; i++) {
                is.addValue(initialStates[s].get(i).getTotalServerTime());
                id.addValue(initialStates[s].get(i).getServerTimeStandardDeviation());
            }
            System.out.println(stageName(s));
            System.out.print("\tTemps total inici " + (int) is.getMean() + " (" + (int) is.getStandardDeviation() + " stdev).");
            System.out.print(" Diferencia entre servers " + (int) id.getMean() + " (" + (int) id.getStandardDeviation() + " stdev).");
            System.out.println();
            SummaryStatistics tt = new SummaryStatistics();
            SummaryStatistics rt = new SummaryStatistics();
            SummaryStatistics sd = new SummaryStatistics();
            SummaryStatistics ns = new SummaryStatistics();
            int noServerd = 0;
            for (int i = 0; i < numIterations; i++) {
                DistFileSystemState state = new DistFileSystemState(initialStates[s].get(i));
                DistFileSystemState last = getLastState(state, searchAgents[s].get(i));
                ns.addValue(last.unallocated.size());
                tt.addValue(last.getTotalServerTime());
                sd.addValue(last.getServerTimeStandardDeviation());
                rt.addValue(runTimes[s].get(i));
                o.print(last.getTotalServerTime() + "\t");
            }
            o.println();
            System.out.print("\tTemps total final " + (int) tt.getMean() + " (" + (int) tt.getStandardDeviation() + " stdev).");
            System.out.print(" Diferencia entre servers " + (int) sd.getMean() + " (" + (int) sd.getStandardDeviation() + " stdev).");
            System.out.print(" Triga " + (int) rt.getMean() + "ms (" + (int) rt.getStandardDeviation() + " stdev) en executar-se.");
            System.out.print(" Peticions no servides: " + ns.getMean() + " " + ns.getStandardDeviation());
            System.out.println();
        }
        o.close();
    }
    public static void main(String[] args) throws Servers.WrongParametersException {
        StagedExperiment se = new StagedExperiment8(123, 5);
        try {
            se.initialitze();
            se.execute();
            se.printServerTime("experiment-8");
        } catch (Exception e) {
            Logger.getLogger(DistFileSystem.class.getName()).log(Level.SEVERE, null, e);
        }
    }
}
